// testing of the dominion.c buyCard() function

#include <stdio.h>
#include <stdlib.h>
#include "dominion.h"
#include "dominion_helpers.h"
#include "rngs.h"

#define MAX_CARD treasure_map

typedef struct gameState Gamestate;

//prints the results of the testing
void print_results(int a, int b){
	double results = ((double)a) / b;
	printf("---------------------\n");
	printf("buyCard() -- %.f%% of test cases passed (%d/%d)\n", (results*100), a, b);
}

//print the current input values
void print_values(Gamestate *g){
	printf("\tplayer = %d\n", g->whoseTurn);
	printf("\tnumBuys = %d\n", g->numBuys);
	printf("\tcoins = %d\n", g->coins);
}
//sets all the values in the game struct to 0
void init_gamestate(Gamestate *g){
	int i;
	for(i = 0; i < sizeof(Gamestate); i++){
		((char *)g)[i] = 0;
	}
}

int main(int argc, char **argv) {
	int i, j;
	int card, cost, player, discardSize;
	int randomSeed, test_count;
	int expected_result, result, status;
	int good_test, bad_test;
	double test_results;
	Gamestate g1, g2;
	
	if(argc != 3){
		printf("Usage: unittest3 [seed] [number of tests]\n");
		return(0);
	}
	
	//initialize vars
	randomSeed = atoi(argv[1]);
	test_count = atoi(argv[2]);
	
	if(test_count < 0){
		printf("Please provide a positive integer for [number of tests]\n");
		return(0);
	}
	good_test = bad_test = 0;
	
	// set up random number
	SelectStream(1);
	PutSeed((long)randomSeed);
	
	for(i = 0; i < test_count; i++){
		//reset the games
		init_gamestate(&g1);
		init_gamestate(&g2);
		
		//create random test inputs
		g1.numBuys = g2.numBuys = (int)(Random()*10); //number of buys
		g1.coins = g2.coins = (int)(Random()*20); //coin count
		card = (int)(Random()*MAX_CARD); //card we're trying to buy
		cost = getCost(card); //cost of the card
		g1.supplyCount[card] = g2.supplyCount[card] = (int)(Random()*4); //number of those cards left
		player = (int)(Random()*3)+1; //player whose turn it is
		g1.whoseTurn = g2.whoseTurn = player;
		g1.deckCount[player] = g2.deckCount[player] = (int)(Random()*MAX_DECK/2);
		for(j = 0; j < g1.deckCount[player]; j++){
			//fill deck with random cards
			g1.deck[player][j] = g2.deck[player][j] = (int)(Random()*MAX_CARD);
		}
		discardSize = (int)(Random()*(MAX_DECK/2)); //discard pile size
		g1.discardCount[player] = g2.discardCount[player] = discardSize;
		for(j = 0; j < discardSize; j++){
			//fill discard pile with random cards
			g1.discard[player][j] = g2.discard[player][j] = (int)(Random()*MAX_CARD);
		}
		
		//set expected results
		expected_result = 0;
		if(g1.numBuys < 1) expected_result = -1;
		if(g1.supplyCount[card] < 1) expected_result = -1;
		if(g1.coins < cost) expected_result = -1;
		
		//make the purchase
		result = buyCard(card, &g1);
		
		//see if we got our expected result
		if(result != expected_result){
			printf("Unexpected Result!\n");
			printf("\texpected %d and got %d\n", expected_result, result);
			print_values(&g2);
			printf("\tcard = %d\n", card);
			bad_test++;
			printf("\tcost = %d\n", cost);
			continue;
		}
		if(result == -1){
			good_test++;
			continue;
		}
		
		//if we did, make sure the game is in the right state
		status = 0;
		if(g1.whoseTurn != g2.whoseTurn){
			printf("Error: wrong person's turn!\n");
			status = -1;
		}
		if(g1.coins + cost != g2.coins){
			printf("Error: wrong number of coins deducted!\n");
			printf("\tshould have %d instead of %d (cost = %d)\n", g2.coins-cost, g1.coins, cost);
			status = -1;
		}
		if(g1.coins < 0){
			printf("Error: number of coins < 0!\n");
			status = -1;
		}
		if(g1.numBuys + 1 != g2.numBuys){
			printf("Error: number of remaining buys incorrect!\n");
			printf("\tshould have %d instead of %d\n", g2.numBuys-1, g1.numBuys);
			status = -1;
		}
		if(g1.numBuys < 0){
			printf("Error: number of remaining buys < 0!\n");
			status = -1;
		}
		if(g1.supplyCount[card]+1 != g2.supplyCount[card]){
			printf("Error: wrong number of cards remaining!\n");
			printf("\tshould have %d instead of %d\n", g2.supplyCount[card]-1, g1.supplyCount[card]);
			status = -1;
		}
		if(g1.supplyCount[card] < 0){
			printf("Error: number of cards remaining < 0!\n");
			status = -1;
		}
		if(g1.discardCount[player]-1 != g2.discardCount[player]){
			printf("Error: wrong number of cards in the discard pile!\n");
			printf("\tshould have %d instead of %d\n", g2.discardCount[player]+1, g1.discardCount[player]);
			status = -1;
		}
		if(g1.discard[player][g2.discardCount[player]] != card){
			printf("Error: card not in the discard pile!\n");
			status = -1;
		}
		
		if(status == -1) bad_test++;
		else good_test++;

	}
	
	print_results(good_test, test_count);
	
	return 0;
}
